//
//  HD_HSP_QRCodeView.m
//  HDQRcodeDemo
//
//  Created by HDHaoShaoPeng on 2017/5/24.
//  Copyright © 2017年 HDHaoShaoPeng. All rights reserved.
//

#import "HD_HSP_QRCodeView.h"
#import <AVFoundation/AVFoundation.h>


@interface HD_HSP_QRCodeView ()<AVCaptureMetadataOutputObjectsDelegate>
@property(strong,nonatomic)AVCaptureSession *session;
@end




@implementation HD_HSP_QRCodeView

{
    NSString *_codeString;
}


-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;
}



/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect {
 // Drawing code
 }
 */



#pragma mark - 生成二维码方法

-(UIImage *)giveMeQRCodeImageWithString:(NSString *)codeString imageSize:(CGFloat)size andLogoImage:(UIImage *)LogoImage
{
    return [self qrImageForString:codeString imageSize:size andLogoImage:LogoImage];
}

- (UIImage *)qrImageForString:(NSString *)string imageSize:(CGFloat)Imagesize andLogoImage:(UIImage*)logoImage
{
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [filter setDefaults];
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    [filter setValue:data forKey:@"inputMessage"];//通过kvo方式给一个字符串，生成二维码
    [filter setValue:@"H" forKey:@"inputCorrectionLevel"];//设置二维码的纠错水平，越高纠错水平越高，可以污损的范围越大
    CIImage *outPutImage = [filter outputImage];//拿到二维码图片
    return [self createNonInterpolatedUIImageFormCIImage:outPutImage withSize:Imagesize andLogoImage:logoImage];
}

//通过bitmap 获取到UIImage
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size andLogoImage:(UIImage *)logoImage
{
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    // 1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    //创建一个DeviceGray颜色空间
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    //CGBitmapContextCreate(void * _Nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef  _Nullable space, uint32_t bitmapInfo)
    //width：图片宽度像素
    //height：图片高度像素
    //bitsPerComponent：每个颜色的比特值，例如在rgba-32模式下为8
    //bitmapInfo：指定的位图应该包含一个alpha通道。
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    //创建CoreGraphics image
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    
    // 2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    
    //原图
    UIImage *outputImage = [UIImage imageWithCGImage:scaledImage];
    
    if (logoImage == nil) {
        return outputImage;
    }
    else
    {
        //给二维码加 logo 图
        UIGraphicsBeginImageContextWithOptions(outputImage.size, NO, [[UIScreen mainScreen] scale]);
        [outputImage drawInRect:CGRectMake(0,0 , size, size)];
        //把logo图画到生成的二维码图片上，注意尺寸不要太大（最大不超过二维码图片的%30），太大会造成扫不出来
        CGFloat waterImagesize = 0.3*size;
        [logoImage drawInRect:CGRectMake((size-waterImagesize)/2.0, (size-waterImagesize)/2.0, waterImagesize, waterImagesize)];
        UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return newPic;
    }
}

#pragma mark - 私有方法

//判断相机使用权限
-(void)adjustCameraPermission
{
    
    if (!TARGET_IPHONE_SIMULATOR) {
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if(authStatus == AVAuthorizationStatusAuthorized)
        {
            [self.session startRunning];
        }
        else if (authStatus == AVAuthorizationStatusDenied)
        {
            if ([self.myDelegate respondsToSelector:@selector(pleaseOpenCameraPermission)]) {
                [self.myDelegate pleaseOpenCameraPermission];//@"请打开使用相机的权限"
            }
        }
        else if (authStatus == AVAuthorizationStatusNotDetermined)//已经拒绝再次提问
        {
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if(granted){
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.session startRunning];
                    });
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.session stopRunning];
                    });
                }}];
        }
    }
    else
    {
        LOG(@"警告：扫码功能只能运行在真机上。");
    }
}

-(void)startRunning
{
    [self adjustCameraPermission];
}

#pragma mark - 懒加载

-(AVCaptureSession *)session
{
    if (!_session) {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
        
        if (input && output) {
            
            [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
            
            _session = [[AVCaptureSession alloc]init];
            [_session setSessionPreset:AVCaptureSessionPresetHigh];
            
            [_session addInput:input];
            [_session addOutput:output];
            output.metadataObjectTypes = @[AVMetadataObjectTypeInterleaved2of5Code,AVMetadataObjectTypeCode93Code,AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeUPCECode,AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code,AVMetadataObjectTypePDF417Code];//AVMetadataObjectTypeDataMatrixCode,AVMetadataObjectTypeITF14Code,AVMetadataObjectTypeAztecCode,AVMetadataObjectTypeCode39Mod43Code,
            
            AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
            layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
            layer.frame = self.bounds;
            [self.layer insertSublayer:layer atIndex:0];
        }
    }
    
    return _session;
}





#pragma mark - AVCaptureMetadataOutputObjectsDelegate

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    if (metadataObjects.count>0) {
        //[session stopRunning];
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
        _codeString = metadataObject.stringValue;
        if ([self.myDelegate respondsToSelector:@selector(giveBackSearchStringWith:)]) {
            [self.myDelegate giveBackSearchStringWith:_codeString];
        }
    }
}

@end
